

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.net.InetSocketAddress;

public class CNIOServerDemo {
	public static void main(String[] args) throws IOException{
		Selector selc = Selector.open();  //打开一个选择器
		ServerSocketChannel ssc = ServerSocketChannel.open();  //打开一个socket通道
		ssc.configureBlocking(false);    //指定ssc这个通道为非阻塞模式
		ssc.socket().bind(new InetSocketAddress(9999));
		//注册代码
		ssc.register(selc,SelectionKey.OP_ACCEPT);    //  后面那个是ops，就是选项，OP_ACCEPT OP_CONNECT OP_READ OP_WRITE
		//执行selector操作，相当于大喊一声,注册在我身上的SelectionKey们，哪一个sk对应的通道已经为当初注册的事件就绪了

		while(true){
			int selcCont = selc.select();
			System.out.println(selcCont);
			if(selcCont >0){
				System.out.println(selc.select());
				//如果sk大于0说明，已经有人就绪了
				Set<SelectionKey> set= selc.selectedKeys();  //这个得先大喊一声 才能做这个操作，set是一个集合，里面是就绪的sk
				Iterator<SelectionKey> it = set.iterator();	//--遍历处理sk对应的通道事件,这里是做一个迭代器
				while(it.hasNext()){
					SelectionKey sk = it.next();    //取出每一个通道对象
					if(sk.isAcceptable()){    //判断是什么操作.其实可以写为sk.interestOps() == SelectionKey.OP_ACCEPT,自动返回布尔类型
						ServerSocketChannel sscx = (ServerSocketChannel)sk.channel();  //拿到sk的通道
						SocketChannel sc = sscx.accept();     //创建accept对象
						sc.configureBlocking(false);    //设置非阻塞模式
						sc.register(selc, SelectionKey.OP_READ);  //读数据
					}else if(sk.isConnectable()){

					}else if(sk.isReadable()){
						//读取客户端发送的数据
						SocketChannel sc = (SocketChannel)sk.channel();

						ByteBuffer temp = ByteBuffer.allocate(1);
						String head = "";
						while (!head.endsWith("\r\n")){     //添加数据包分割符
							sc.read(temp);
							head += new String(temp.array());
							temp.clear();
						}
						int len = Integer.parseInt(head.substring(0,head.length()-2));
						ByteBuffer buf = ByteBuffer.allocate(len);

						while(buf.hasRemaining()){
							sc.read(buf);       //把数据填充到缓冲区
						}

//						sc.read(buf);
						String msg = new String(buf.array(),"utf-8");
						System.out.println("服务器收到了"+sc.socket().getInetAddress()+"发来的："+msg);

					}else if(sk.isWritable()){


					}else{
						throw new RuntimeException("selector操作方式出错");
					}
					it.remove();   //清楚已处理过后的键，不删除会重复处理
				}
			}
		}


	}


}